﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
using Library;

namespace Ta_La
{
    public partial class Form1 : Form
    {
        Socket _socketServer, _socketClient;
        List<AClient> _listClient;
        BoBai bobai = new BoBai();
        byte[] _buffer;
        int count=0;
        public Form1()
        {
            CheckForIllegalCrossThreadCalls = false;
            _listClient = new List<AClient>();
            _buffer = new byte[1024];
            InitializeComponent();          
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Start();
        }
        private List<LaBai> Chia()
        {
            var list = BoBai.Randomize(bobai.list, 9);
            return list;
        }
        private void Start()
        {
            _socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            _socketServer.Bind(new IPEndPoint(IPAddress.Loopback, 8888));
            _socketServer.Listen(4);
            try
            {
                textBox.AppendText("Server da khoi dong va dang cho ket noi \r\n");
                _socketServer.BeginAccept(AcceptCallBack, null);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        private void AcceptCallBack(IAsyncResult AR)
        {
            try
            {
                var _socketClient = _socketServer.EndAccept(AR);
                textBox.AppendText(string.Format("have a client conntec on {0} {1}", _socketClient.RemoteEndPoint, "\t\n"));
                _socketServer.BeginAccept(AcceptCallBack, null);
                _socketClient.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, ReceiveCallBack, _socketClient);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        private void frmFormServer_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (_socketServer != null)
            {
                _listClient.ForEach(p =>
                {
                    p.Connector.Close();
                });
                _socketServer.Close();
            }
        }
        private void ReceiveCallBack(IAsyncResult AR)
        {
            try
            {
                _socketClient = AR.AsyncState as Socket;
                _socketClient.EndReceive(AR);
                ChatMessage msg = new ChatMessage(_buffer);
                var sendmsg = new ChatMessage(msg.UserName, msg.CmdType, string.Empty);
                byte[] send;

                switch (msg.CmdType)
                {
                    case Command.Login:
                        textBox.AppendText(msg.UserName + "\n");
                        _listClient.Add(new AClient()
                        {
                            Connector = this._socketClient,
                            UserName = msg.UserName
                        });
                        sendmsg.Message = string.Format("<<<{0} da tham gia phong chat>>>", msg.UserName);
                        break;
                    case Command.Logout:
                        _listClient.RemoveAll(p => p.Connector == _socketClient);
                        sendmsg.Message = string.Format(
                            "<<<{0} thoat khoi phong chat >>>", msg.UserName);
                        break;
                    case Command.List:
                        sendmsg.Message = _listClient.Count.ToString();
                        send = sendmsg.TobyteArray();
                        _listClient.ForEach(p =>
                        {
                            p.Connector.BeginSend(send, 0, send.Length, SocketFlags.None, SendCallBack, p.Connector);
                        });
                        break;
                    case Command.Start:
                        string m="";
                        _listClient.ForEach(p =>
                        {
                            m = "";
                            var list1 = Chia();
                            list1.ForEach(c => m += c.So + " " + c.Ten + "*");
                            sendmsg.Message = m;
                            send = sendmsg.TobyteArray();
                            p.Connector.BeginSend(send, 0, send.Length, SocketFlags.None, SendCallBack, p.Connector);
                        });                              
                        break;
                    case Command.SanSang:
                        count ++;
                        if(count==_listClient.Count)
                        {
                            var bodem=msg.TobyteArray();
                            _listClient[0].Connector.BeginSend(bodem, 0, bodem.Length, SocketFlags.None, SendCallBack, _listClient[0].Connector);
                        }
                        break;
                    case Command.Message:
                        string clientname = msg.UserName;
                        string message = msg.Message;
                        textBox.AppendText(clientname + " says:" + message + "\n");
                        sendmsg.Message = message;
                        break;
                    case Command.Luot:
                        int index1 = _listClient.FindIndex(p => p.Connector == _socketClient)+1;
                        if (index1 == 4)
                            index1 = 0;
                        var buffer1=sendmsg.TobyteArray();
                        _listClient[index1].Connector.BeginSend(buffer1,0,buffer1.Length,SocketFlags.None,SendCallBack,_listClient[index1].Connector);
                        break;
                    case Command.CayRac:
                        int index = _listClient.FindIndex(p => p.Connector == _socketClient)+1;
                        sendmsg.Message = msg.Message+"*"+ index;
                        if (index == 4)
                            index = 0;
                        var buffer=sendmsg.TobyteArray();
                        _listClient[index].Connector.BeginSend(buffer,0,buffer.Length,SocketFlags.None,SendCallBack,_listClient[index].Connector);
                        break;
                    case Command.Boc:
                        var lb=BoBai.Randomize(bobai.list, 1).Single();
                        sendmsg.Message = lb.So+" "+lb.Ten;
                        send = sendmsg.TobyteArray();
                        _socketClient.BeginSend(send, 0, send.Length, SocketFlags.None, SendCallBack, _socketClient);
                        break;
                    case Command.Chot:
                        break;
                    case Command.An:
                        break;
                    case Command.None:
                        break;
                    default:
                        break;
                }
                if (msg.CmdType != Command.List && msg.CmdType != Command.Start && msg.CmdType != Command.Boc && msg.CmdType!=Command.CayRac)
                {
                    send = sendmsg.TobyteArray();
                    _listClient.ForEach(p =>
                    {
                        if (p.Connector != _socketClient)
                            p.Connector.BeginSend(send, 0, send.Length, SocketFlags.None,SendCallBack, p.Connector);
                    });
                }
                if (msg.CmdType != Command.Logout)
                {
                    _listClient.ForEach(p=>
                        {
                            p.Connector.BeginReceive(_buffer, 0, _buffer.Length,
                                SocketFlags.None, ReceiveCallBack, p.Connector);
                        });
                }   
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        private void SendCallBack(IAsyncResult AR)
        {
            try
            {
                var client = AR.AsyncState as Socket;
                client.EndSend(AR);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
    }
}
